#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
邮件提醒系统 - 主程序
功能：获取当日天气信息并发送打卡提醒邮件
作者： gitee：@xyy852
日期：2025-09-11
"""

import json
import logging
import os
import sys
import time
import threading
from datetime import datetime, time as dt_time
from typing import Dict, Any, List

from weather_module import WeatherAPI
from email_module import EmailSender


class DailyReminder:
    """每日提醒系统主类"""
    
    def __init__(self, config_file: str = "config.json"):
        """
        初始化每日提醒系统
        
        Args:
            config_file: 配置文件路径
        """
        self.config_file = config_file
        self.config = self._load_config()
        self._setup_logging()
        
        # 初始化模块
        self.weather_api = WeatherAPI(self.config.get('weather', {}))
        self.email_sender = EmailSender(self.config.get('email', {}))
        
        # 定时器相关
        self.scheduler_running = False
        self.scheduler_thread = None
        
    def _load_config(self) -> Dict[str, Any]:
        """加载配置文件"""
        try:
            if not os.path.exists(self.config_file):
                self._create_default_config()
                print(f"已创建默认配置文件：{self.config_file}")
                print("请编辑配置文件后重新运行程序")
                sys.exit(1)
                
            with open(self.config_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        except Exception as e:
            print(f"加载配置文件失败：{e}")
            sys.exit(1)
    
    def _create_default_config(self):
        """创建默认配置文件"""
        default_config = {
            "weather": {
                "api_key": "YOUR_WEATHER_API_KEY",
                "city": "北京",
                "api_provider": "openweathermap"
            },
            "email": {
                "smtp_server": "smtp.qq.com",
                "smtp_port": 587,
                "sender_email": "your_email@qq.com",
                "sender_password": "your_app_password",
                "recipient_emails": ["recipient@example.com"]
            },
            "reminder": {
                "work_start_time": "09:00",
                "work_end_time": "18:00",
                "custom_messages": [
                    "记得按时打卡哦！",
                    "新的一天开始了，加油！",
                    "工作愉快，记得打卡！"
                ]
            },
            "logging": {
                "level": "INFO",
                "file": "reminder.log"
            }
        }
        
        with open(self.config_file, 'w', encoding='utf-8') as f:
            json.dump(default_config, f, ensure_ascii=False, indent=4)
    
    def _setup_logging(self):
        """设置日志"""
        log_config = self.config.get('logging', {})
        log_level = getattr(logging, log_config.get('level', 'INFO'))
        log_file = log_config.get('file', 'reminder.log')
        
        logging.basicConfig(
            level=log_level,
            format='%(asctime)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler(log_file, encoding='utf-8'),
                logging.StreamHandler()
            ]
        )
        self.logger = logging.getLogger(__name__)
    
    def get_current_time_info(self) -> Dict[str, str]:
        """获取当前时间信息"""
        import locale
        
        # 设置中文编码
        try:
            locale.setlocale(locale.LC_ALL, 'zh_CN.UTF-8')
        except locale.Error:
            try:
                locale.setlocale(locale.LC_ALL, 'Chinese_China.936')
            except locale.Error:
                pass  # 使用默认编码
        
        now = datetime.now()
        try:
            # 尝试使用strftime格式化
            date_str = now.strftime('%Y年%m月%d日')
            weekdays = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']
            weekday_str = weekdays[now.weekday()]
        except UnicodeEncodeError:
            # 如果编码失败，使用英文格式
            date_str = now.strftime('%Y-%m-%d')
            weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
            weekday_str = weekdays[now.weekday()]
        
        return {
            'date': date_str,
            'time': now.strftime('%H:%M'),
            'weekday': weekday_str
        }
    
    def generate_reminder_message(self, weather_info: Dict[str, Any]) -> str:
        """生成提醒邮件内容"""
        time_info = self.get_current_time_info()
        custom_messages = self.config.get('reminder', {}).get('custom_messages', [])
        
        # 构建邮件内容
        # 安全处理中文字符
        try:
            city = weather_info.get('city', 'Unknown')
            description = weather_info.get('description', 'Unknown')
            temperature = weather_info.get('temperature', 'Unknown')
            feels_like = weather_info.get('feels_like', 'Unknown')
            humidity = weather_info.get('humidity', 'Unknown')
            suggestion = weather_info.get('suggestion', '')
            work_start = self.config.get('reminder', {}).get('work_start_time', '09:00')
            work_end = self.config.get('reminder', {}).get('work_end_time', '18:00')
            custom_msg = custom_messages[0] if custom_messages else 'Remember to clock in!'
            
            message = f"""
📅 每日提醒 - {time_info['date']} {time_info['weekday']}

🌤️ 天气信息:
城市: {city}
天气: {description}
温度: {temperature}°C
体感温度: {feels_like}°C
湿度: {humidity}%
建议：{suggestion}

⏰ 工作时间段:
{work_start} - {work_end}

💡 小贴士:
{custom_msg}

祝你今天过得愉快！

---
📧 自动发送电子邮件提醒系统
🕐 发送时间: {time_info['date']} {time_info['time']}
"""
        except UnicodeEncodeError:
            # 如果仍有编码问题，使用最简单的英文版本
            message = f"""
Daily Reminder - {time_info['date']}

Weather: {weather_info.get('temperature', 'N/A')}°C
Reminder: Don't forget to clock in!

Sent at: {time_info['time']}
"""
        
        return message.strip()
    
    def is_scheduled_time(self) -> bool:
        """检查当前是否为计划发送时间"""
        now = datetime.now()
        current_time = now.strftime('%H:%M')
        
        scheduled_times = self.config.get('reminder', {}).get('scheduled_times', [])
        return current_time in scheduled_times
    
    def get_next_scheduled_time(self) -> str:
        """获取下一次计划发送时间"""
        scheduled_times = self.config.get('reminder', {}).get('scheduled_times', [])
        if not scheduled_times:
            return "未设置计划时间"
        
        now = datetime.now()
        current_time_str = now.strftime('%H:%M')
        
        # 将时间字符串转换为时间对象以便比较
        try:
            current_hour, current_min = map(int, current_time_str.split(':'))
            current_time = current_hour * 60 + current_min  # 转换为分钟数
        except ValueError:
            return "时间格式错误"
        
        next_times = []
        for time_str in scheduled_times:
            try:
                hour, minute = map(int, time_str.split(':'))
                scheduled_minutes = hour * 60 + minute
                if scheduled_minutes > current_time:
                    next_times.append(time_str)
            except ValueError:
                continue
        
        if next_times:
            return min(next_times)
        else:
            # 如果今天没有了，返回明天的第一个时间
            return f"明天 {min(scheduled_times)}"
    
    def wait_for_scheduled_time(self):
        """等待下一个计划时间"""
        while self.scheduler_running:
            if self.is_scheduled_time():
                self.logger.info("到达计划发送时间，开始发送邮件...")
                self.send_reminder()
                # 等待61秒以避免在同一分钟内重复发送
                time.sleep(61)
            else:
                # 每10秒检查一次
                time.sleep(10)
    
    def start_scheduler(self):
        """启动定时调度器"""
        if self.scheduler_running:
            self.logger.warning("定时调度器已经在运行")
            return
        
        scheduled_times = self.config.get('reminder', {}).get('scheduled_times', [])
        if not scheduled_times:
            self.logger.error("未配置计划发送时间")
            return
        
        self.scheduler_running = True
        self.scheduler_thread = threading.Thread(target=self.wait_for_scheduled_time, daemon=True)
        self.scheduler_thread.start()
        
        next_time = self.get_next_scheduled_time()
        self.logger.info(f"定时调度器已启动，计划发送时间: {', '.join(scheduled_times)}")
        self.logger.info(f"下一次发送时间: {next_time}")
        print(f"🌅 定时调度器已启动")
        print(f"⏰ 计划发送时间: {', '.join(scheduled_times)}")
        print(f"⏳ 下一次发送: {next_time}")
    
    def stop_scheduler(self):
        """停止定时调度器"""
        self.scheduler_running = False
        if self.scheduler_thread:
            self.scheduler_thread.join(timeout=1)
        self.logger.info("定时调度器已停止")
        print("⏹️ 定时调度器已停止")
    
    def send_reminder(self):
        """发送提醒邮件（单次执行）"""
        try:
            self.logger.info("开始运行每日提醒系统")
            
            # 获取天气信息
            self.logger.info("正在获取天气信息...")
            weather_info = self.weather_api.get_weather()
            
            if not weather_info:
                self.logger.error("获取天气信息失败")
                weather_info = {
                    'city': self.config.get('weather', {}).get('city', '未知城市'),
                    'description': '暂时无法获取天气信息',
                    'temperature': '未知',
                    'feels_like': '未知',
                    'humidity': '未知',
                    'suggestion': '请注意关注天气变化'
                }
            
            # 生成提醒内容
            message_content = self.generate_reminder_message(weather_info)
            
            # 发送邮件
            time_info = self.get_current_time_info()
            
            # 从配置文件获取邮件标题模板
            subject_template = self.config.get('reminder', {}).get('email_subject_template', 
                                                                 '🌅 每日打卡提醒 - {date} {weekday}')
            
            try:
                subject = subject_template.format(
                    date=time_info['date'], 
                    weekday=time_info['weekday']
                )
            except (UnicodeEncodeError, KeyError):
                subject = f"Daily Clock-in Reminder - {time_info['date']}"
            
            self.logger.info("正在发送提醒邮件...")
            success = self.email_sender.send_email(
                subject=subject,
                content=message_content,
                recipients=self.config.get('email', {}).get('recipient_emails', [])
            )
            
            if success:
                self.logger.info("邮件发送成功！")
                print(f"✅ [{time_info['time']}] 邮件发送成功！")
            else:
                self.logger.error("邮件发送失败")
                print(f"❌ [{time_info['time']}] 邮件发送失败，请检查配置和日志")
                
        except Exception as e:
            self.logger.error(f"运行过程中出现错误：{e}")
            print(f"❌ 运行失败：{e}")
    
    def run(self, mode="once"):
        """
        运行每日提醒系统
        
        Args:
            mode: 运行模式
                - "once": 立即执行一次（默认）
                - "schedule": 启动定时调度器
        """
        if mode == "once":
            self.send_reminder()
        elif mode == "schedule":
            self.start_scheduler()
            try:
                # 保持程序运行
                while self.scheduler_running:
                    time.sleep(1)
            except KeyboardInterrupt:
                print("\n⏹️ 用户中断程序")
                self.stop_scheduler()
        else:
            raise ValueError(f"不支持的运行模式: {mode}")


def main():
    """主函数"""
    print("🌅 每日提醒系统启动中...")
    
    # 检查命令行参数
    if len(sys.argv) > 1 and sys.argv[1] == "--schedule":
        mode = "schedule"
        print("🕰️ 定时模式启动...")
    else:
        mode = "once"
        print("⚡ 单次执行模式...")
    
    try:
        reminder = DailyReminder()
        reminder.run(mode=mode)
    except KeyboardInterrupt:
        print("\n⏹️ 用户中断程序")
    except Exception as e:
        print(f"❌ 程序运行失败：{e}")
        sys.exit(1)


if __name__ == "__main__":
    main()